#include "ConfModule.h"

QScopedPointer<ConfModule> ConfModule::ms_instance;
ConfModule::ConfModule(QObject *parent)
    :BaseModule(s_moduleName,parent)
    ,m_timer(new QTimer(this))
    ,m_fileSystemWatcher(new QFileSystemWatcher(this))
    ,m_defaultFilePath(KylinDaqCommon::gs_defaultConfFilePath)
    ,m_cacheFolderPath(KylinDaqCommon::gs_cacheFolderPath)
    ,m_confFileName(KylinDaqCommon::gs_confFileName)
{
    checkDir(m_cacheFolderPath);
    m_fileSystemWatcher->addPath(m_cacheFolderPath);
    m_fileSystemWatcher->addPath(m_cacheFolderPath+m_confFileName);
    m_fileSystemWatcher->addPath(m_defaultFilePath);
    connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged,this, &ConfModule::checkDir);
    connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, &ConfModule::readConf);
    connect(m_timer, &QTimer::timeout, this, &ConfModule::getConf);
    connect(this , &ConfModule::pollingIntervalChanged ,this, &ConfModule::setTimePollingInterval);
}

ConfModule::~ConfModule()
{

}

ConfModule* ConfModule::instance(void)
{
    if (ms_instance.isNull()) {
        ms_instance.reset(new ConfModule());
    }
    return ms_instance.data();
}

void ConfModule::setTimePollingInterval(qlonglong sec)
{
    m_timer->stop();
    m_timer->setInterval(KylinDaqCommon::secToMsec(sec));
    m_timer->start();
}

QJsonObject ConfModule::readJson(const QString &filePath)
{

    QFile file(filePath);
    QJsonDocument jsonDoc;
    QJsonObject jsonObj;
    if(file.exists())
    {
        if(file.open(QFile::OpenModeFlag::ReadOnly))
        {
            jsonDoc = QJsonDocument::fromJson(file.readAll());
            if(jsonDoc.isObject())
            {
                jsonObj = jsonDoc.object();
            }
            else
            {
                qWarning()<<"c = "<<jsonDoc;
                qWarning()<<filePath<<" don't json object";
            }
            file.close();
        }
        else
        {
            qWarning()<<filePath<<" don't opened";
        }
    }
    else{
        qWarning()<<filePath<<" don't exist";
    }
    return jsonObj;
}

void ConfModule::writeJson(const QString &filePath, QJsonObject &jsonObj)
{
    QFile file(filePath);
    int32_t writeByteNum;
    if(!file.open(QIODevice::ReadWrite|QIODevice::Truncate))
    {
        qWarning() << "DeviceConf:openFailed " << file.errorString();
        return;
    }
    writeByteNum = file.write(QJsonDocument(jsonObj).toJson(QJsonDocument::Indented));
    if(writeByteNum <= 0)
    {
        qWarning() << "DeviceConf:writeByteNum="<<writeByteNum;
    }
    file.close();
}

void ConfModule::readConf(const QString &filePath)
{
    QJsonObject defaultConfJsonObj = readJson(m_defaultFilePath);
    QJsonObject confJsonObj = readJson(filePath);
    QJsonObject sendConfJsonObj;
    for(auto iter = defaultConfJsonObj.begin();iter != defaultConfJsonObj.end();iter++)
    {
        if(iter.value().isObject())
        {
            QString moduleName = iter.key();
            if(!confJsonObj.isEmpty()
                && confJsonObj.contains(moduleName)
                && confJsonObj[moduleName].isObject())
            {
                sendConfJsonObj.insert(moduleName,confJsonObj[moduleName].toObject());
            }
        }
    }
    if(!sendConfJsonObj.isEmpty() && !defaultConfJsonObj.isEmpty())
    {
        qDebug()<<"ConfModule::readConf: file="<<m_fileSystemWatcher->files();
        emit sendConf(sendConfJsonObj,defaultConfJsonObj);
    }
    if(!m_fileSystemWatcher->files().contains(filePath))
    {
        m_fileSystemWatcher->addPath(filePath);
    }
}

void ConfModule::updateProperty(const QJsonObject &conf, const QJsonObject &defaultConf)
{
    qlonglong value;
    KylinDaqCommon::setValidConfInt(conf, defaultConf, moduleName(), s_pollingIntervalKey, value);
    setPollingInterval(value);
}

void ConfModule::writeConf(const QString &moduleName, const QString &key, const QVariant &value)
{
    QJsonObject confJsonObj = readJson(m_cacheFolderPath+m_confFileName);
    QJsonObject moduleJsonObj;
    if(confJsonObj.contains(moduleName)&&confJsonObj[moduleName].isObject())
    {
        moduleJsonObj = confJsonObj[moduleName].toObject();
        moduleJsonObj[key] = value.toJsonValue();
        confJsonObj[moduleName] = moduleJsonObj;
    }
    else
    {
        moduleJsonObj[key] = value.toJsonValue();
        confJsonObj.insert(moduleName,moduleJsonObj);
    }
    writeJson(m_cacheFolderPath+m_confFileName,confJsonObj);
    if(!m_fileSystemWatcher->files().contains(m_cacheFolderPath+m_confFileName))
    {
        m_fileSystemWatcher->addPath(m_cacheFolderPath+m_confFileName);
    }
}

void ConfModule::writeConf2(const QString &conf)
{
    qDebug()<<"ConfModule::wirteConf2: "<<conf;
    bool updateConf = false;
    QJsonObject defaultConfJsonObj = readJson(m_defaultFilePath);
    QJsonObject confJsonObj = readJson(m_cacheFolderPath+m_confFileName);
    QJsonDocument jsonDoc = QJsonDocument::fromJson(conf.toUtf8());
    if (!jsonDoc.isObject())
    {
        return;
    }
    QJsonObject jsonObj = jsonDoc.object();
    for (auto moduleIter = jsonObj.begin();moduleIter != jsonObj.end();moduleIter++)
    {
        QString moduleName = moduleIter.key();
        if (!defaultConfJsonObj.contains(moduleName))
        {
            continue;
        }
        if (!moduleIter.value().isObject())
        {
            continue;
        }
        QJsonObject defaultModuleConfJsonObj= defaultConfJsonObj[moduleName].toObject();
        QJsonObject moduleConfJsonObj = confJsonObj[moduleName].toObject();
        QJsonObject moduleJsonObj = moduleIter.value().toObject();
        for (auto moduleConfIter = moduleJsonObj.begin();moduleConfIter != moduleJsonObj.end();moduleConfIter++)
        {
            QString moduleConfKey = moduleConfIter.key();
            if (!defaultModuleConfJsonObj.contains(moduleConfKey))
            {
                continue;
            }
            if(moduleName != s_transmitModuleKey || moduleConfKey != s_transmitModuleUploadStateKey) 
            {
                moduleConfJsonObj[moduleConfKey] = moduleConfIter.value();

            }
            updateConf = true;
        }
        confJsonObj[moduleName] = moduleConfJsonObj;
    }
    if (updateConf == true)
    {
        qInfo()<<"ConfModule::writeConf2 change config";
        writeJson(m_cacheFolderPath+m_confFileName,confJsonObj);
        if(!m_fileSystemWatcher->files().contains(m_cacheFolderPath+m_confFileName))
        {
        m_fileSystemWatcher->addPath(m_cacheFolderPath+m_confFileName);
        }

    }

}

void ConfModule::checkDir(const QString &folderPath)
{
    QDir tempDir(folderPath);
    if(!tempDir.exists())
    {
        tempDir.mkpath(folderPath);
    }
}
